package com.oracle.shiro;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import com.oracle.admin.service.api.AdminServiceApi;
import com.oracle.lintener.InitLintener;
import com.oracle.pojo.Admins;
import com.oracle.properties.PropertiesUtils;
import com.oracle.utils.HttpUtils;
import com.oracle.vo.ResultEntity;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import org.springframework.beans.factory.annotation.Autowired;

public class AuthenticationRealm extends AuthorizingRealm{
	
	@Autowired(required = false)
	private AdminServiceApi adminServiceApi;
	@Autowired
    private PropertiesUtils propertiesUtils;


    /**
     *  赋予权限
     * @param principals
     * @return
     */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
	    //获取令牌
		Principal principal=(Principal) principals.fromRealm(getName()).iterator().next();
		//判断令牌是否为空
		if(principal!=null) {
		    //根据令牌中的adminid获取管理员下的权限集合
            ResultEntity<List<String>> resultEntity = this.adminServiceApi.getpermissionByLoginid(principal.getId());
            List<String> listPer = resultEntity.getData();
                if(listPer!=null) {
                    System.out.println("执行doGetAuthorizationInfo");
                    SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
                    authorizationInfo.addStringPermissions(listPer);
                    return authorizationInfo;
                }
		}
		return null;
	}


    /**
     * 认证操作
     * @param token
     * @return
     * @throws AuthenticationException
     */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        AuthenticationToKen authenticationToKen=(AuthenticationToKen) token;
        System.out.println("执行doGetAuthenticationInfo");
	    //获取用户名密码
		String loginName=authenticationToKen.getUsername();
		String password=new String(authenticationToKen.getPassword());
		if(!authenticationToKen.isValid()) {
			throw new UnsupportedTokenException();
		}
		if(loginName!=null&&!"".equals(loginName)) {
            ResultEntity<Admins> resultEntity = this.adminServiceApi.findAdminByLoginname(loginName);
            Admins admin = resultEntity.getData();
            if(admin==null) {
                throw new UnknownAccountException();
            }
            //添加登录三次锁定代码
            //判断是否是锁定状态
            if(admin!=null && Admins.LOCK_LOGIN.equals(admin.getStatus())){
                //锁定状态判断是否已经达到解锁时间
                if (admin.getLockexpirtdate()!=null && !new Date().after(admin.getLockexpirtdate())){
                    //没有到达解锁时间
                    throw new LockedAccountException();
                }
            }
            //解锁的或没有上锁的进行判断密码是否正确
			if(!admin.getPwd().equals(password)) {
                //密码错误进行修改数据库，密码错误次数
                if (admin.getFailcount()!=null && admin.getFailcount()+1==Integer.parseInt(this.propertiesUtils.getValue("failcountmax"))){
                    //清空错误次数
                    admin.setFailcount(0);
                    //设置锁定状态
                    admin.setLockexpirtdate(DateUtils.addMinutes(new Date(),3));
                    admin.setStatus(Admins.LOCK_LOGIN);
                    this.adminServiceApi.updateAdmin(admin);
                    throw new IncorrectCredentialsException();
                }
                //没有到达三次错误进行修改错误次数
                admin.setFailcount(admin.getFailcount()+1);
                this.adminServiceApi.updateAdmin(admin);
				throw new IncorrectCredentialsException();
			}
			//登陆成功
            admin.setFailcount(0);
            admin.setStatus(0);
            admin.setLockexpirtdate(null);
            this.adminServiceApi.updateAdmin(admin);
            admin.setPwd(null);
			return new SimpleAuthenticationInfo(new Principal(admin.getId(), loginName,admin.getRolename()), password, getName());
		}
		return null;
	}

	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
